package raytracer.objects;

import raytracer.math.Vector3d;
import raytracer.misc.Ray;


/**
 * 
 * @author Thorsten Roth
 * @version 11.10.2006
 */
public class Sphere extends ThreeDObject {

	private Vector3d center;
	private double radius;
	
	public Sphere(Vector3d center, double radius) {
		super();
		this.center=center;
		this.radius=radius;
	}
	
	public Vector3d getCenter() {
		return center;
	}
	
	public Double intersect(Ray ray, Vector3d intersectionPoint, Vector3d normal) {
		double t0;
		double t1;
		double t;
		Vector3d direction=new Vector3d(ray.getDirection());
		Vector3d origin=new Vector3d(ray.getOrigin());
		
		double b=2*(
				 	 direction.x*(origin.x-center.x)
				 	+direction.y*(origin.y-center.y)
				 	+direction.z*(origin.z-center.z)
			  	 );
		double c=Math.pow(origin.x-center.x,2)
				+Math.pow(origin.y-center.y,2)
				+Math.pow(origin.z-center.z,2)
				-Math.pow(radius,2);
		
		double diskriminante=Math.pow(b,2)-4*c;
				
		if (diskriminante>0) {
			t0=(-b-Math.sqrt(diskriminante))/2;
			t1=(-b+Math.sqrt(diskriminante))/2;
			t=Math.min(t0,t1);
			
			if (intersectionPoint!=null) {
				intersectionPoint.x=origin.x+t*direction.x;
				intersectionPoint.y=origin.y+t*direction.y;
				intersectionPoint.z=origin.z+t*direction.z;
			}
			
			if (normal!=null) {
				normal.x=(intersectionPoint.x-center.x)/radius;
				normal.y=(intersectionPoint.y-center.y)/radius;
				normal.z=(intersectionPoint.z-center.z)/radius;
				normal.normalize();
			}
						
			return t;
			
		}
		else {
			return null;
		}
		
	}

	@Override
	public double getMaxX() {
		return center.x+radius;
	}

	@Override
	public double getMaxY() {
		return center.y+radius;
	}

	@Override
	public double getMaxZ() {
		return center.z+radius;
	}

	@Override
	public double getMinX() {
		return center.x-radius;
	}

	@Override
	public double getMinY() {
		return center.y-radius;
	}

	@Override
	public double getMinZ() {
		return center.z-radius;
	}

	@Override
	public boolean isInfinite() {
		return false;
	}
	
}